#include "curl_util.h"

#include <buola/buola.h>
#include <buola/net/chttprequest.h>
#include <buola/net/chttpform.h>
#include <buola/xml.h>
#include <buola/io.h>

namespace buola { namespace io {

class CHTTPRequest::SImpl
{
public:
    SImpl()
    :   mCURL(curl_easy_init())
    ,   mHeaders(nullptr)
    {}

    ~SImpl()
    {
        curl_easy_cleanup(mCURL);
        curl_slist_free_all(mHeaders);
    }

    CURL *mCURL;
    struct curl_slist *mHeaders;
};

CHTTPRequest::CHTTPRequest()
    :   mImpl(new SImpl)
{
}

CHTTPRequest::CHTTPRequest(const CURI &pURI)
    :   mImpl(new SImpl)
{
    SetURI(pURI);
}

CHTTPRequest::~CHTTPRequest()
{
}

void CHTTPRequest::SetURI(const CURI &pURI)
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_URL,pURI.ToString().c_str());
}

void CHTTPRequest::SetPost(const CHTTPForm &pForm)
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_COPYPOSTFIELDS, pForm.GetText().c_str());
}

void CHTTPRequest::SetPost(const xml::CDoc &pDoc)
{
    std::string lString=pDoc.ToString();
    msg_info() << "###" << lString << "###\n";
    SetPost("text/xml",lString);
}

void CHTTPRequest::SetPost(const std::string &pType,const std::string &pContent)
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_POSTFIELDSIZE,pContent.size());
    curl_easy_setopt(mImpl->mCURL,CURLOPT_COPYPOSTFIELDS,pContent.data());
    AddHeader("Content-Type",pType);
}

void CHTTPRequest::SetGet()
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_HTTPGET, (long)1);
}

void CHTTPRequest::SetFollowLocation(bool pFollow)
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_FOLLOWLOCATION, (long)pFollow);
}

void CHTTPRequest::AddHeader(const std::string &pHeader)
{
    mImpl->mHeaders=curl_slist_append(mImpl->mHeaders,pHeader.c_str());
    curl_easy_setopt(mImpl->mCURL,CURLOPT_HTTPHEADER,mImpl->mHeaders);
}

void CHTTPRequest::AddHeader(const std::string &pName,const std::string &pValue)
{
    if(pValue.empty())
        AddHeader(pName+":");
    else
        AddHeader(pName+": "+pValue);
}

void CHTTPRequest::ClearHeaders()
{
    if(mImpl->mHeaders)
        curl_slist_free_all(mImpl->mHeaders);
    curl_easy_setopt(mImpl->mCURL,CURLOPT_HTTPHEADER,nullptr);
}

int CHTTPRequest::Perform(std::string &pResult)
{
    curl_easy_setopt(mImpl->mCURL,CURLOPT_WRITEFUNCTION,curl_write_callback_str);
    curl_easy_setopt(mImpl->mCURL,CURLOPT_WRITEDATA,(void*)&pResult);
    curl_check_error(curl_easy_perform(mImpl->mCURL));

    long int lCode;

    curl_check_error(curl_easy_getinfo(mImpl->mCURL,CURLINFO_RESPONSE_CODE,&lCode));

    msg_info() << "result:" << pResult << "\n";
    
    return lCode;
}

CURI CHTTPRequest::GetRedirectURI()
{
    char *lURI;
    curl_check_error(curl_easy_getinfo(mImpl->mCURL,CURLINFO_REDIRECT_URL,&lURI));

    return uri(lURI);
}

/*namespace io*/ } /*namespace buola*/ }
